/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved.
 *
 */

import fs from 'fs-extra';
import { glob } from 'glob';
import path from 'path';

import { CopyConfig, getCopyOptions } from '../../utils/copy-resources-util.js';

/**
 * 指定要copy的模式
 */
export interface PatternObjType {
  src: string;
  dest: string;
  ignore?: Ignore;
  onlyFiles?: boolean;
  rename?: (name: string, extension: string, fullPath: string) => string;
}

interface Ignore {
  ignored: (p: { path: string; name: string }) => boolean;
}

interface Target {
  src: string;
  dest: string;
  rename?: string | Function;
  ignore?: Ignore;
  onlyFiles?: boolean;
}

export interface CopyOptions {
  targets?: Target[];
}

export async function copyByCopyOptions(config: CopyConfig) {
  const copyOptions = getCopyOptions(config);
  const { targets = [], ...restOptions } = copyOptions;

  let copyTargets: Target[] = [];
  if (Array.isArray(targets) && targets.length) {
    copyTargets = await getCopyTargets(targets, restOptions);
  }

  for (const copyTarget of copyTargets) {
    const { dest, src } = copyTarget;
    if (fs.existsSync(src)) {
      copyFile(dest, src);
    }
  }
}

async function getCopyTargets(targets: Target[], restOptions: object) {
  const copyTargets = [];
  for (const target of targets) {
    const { dest, rename, src, ...restTargetOptions } = target;
    const matchedPathArray = glob.sync(src, {
      nodir: true,
      ...restOptions,
      ...restTargetOptions,
    });

    if (matchedPathArray.length) {
      for (const matchedPath of matchedPathArray) {
        const { base } = path.parse(matchedPath);
        copyTargets.push({
          src: matchedPath,
          dest: path.join(dest, rename ? renameTarget(base, rename, matchedPath) : base),
          renamed: rename,
        });
      }
    }
  }
  return copyTargets;
}

function renameTarget(target: string, rename: string | Function, src: string) {
  const parsedPath = path.parse(target);
  return typeof rename === 'string' ? rename : rename(parsedPath.name, parsedPath.ext.replace('.', ''), src);
}

function copyFile(dest: string, src: string) {
  const destDirname = path.dirname(dest);
  fs.ensureDirSync(destDirname);
  fs.copyFileSync(src, dest);
}
